package kz.edu.sdu.itech.pcs.server;

import java.io.IOException;
import java.net.ServerSocket;
import java.util.HashSet;

import kz.edu.sdu.itech.pcs.common.Alphabet;
import kz.edu.sdu.itech.pcs.common.Message;
import kz.edu.sdu.itech.pcs.common.MessageType;
import kz.edu.sdu.itech.pcs.common.Permutations;
import kz.edu.sdu.itech.pcs.common.ServerStatus;

import org.apache.log4j.Logger;

public class Server {
   static Logger log = Logger.getLogger(Server.class);

   ServerSocket monitorSocket;
   ServerSocket workingSocket;
   int monitorPort = 3333, workingPort = 4444;

   MonitorListener monitorListener;

   WorkerListener workerListener;
   HashSet<Worker> workerSet = new HashSet<Worker>();

   ServerStatus status = ServerStatus.WAITING;
   ServerJob currentJob;

   public Server() {
   }

   public void init() {
      try {
         monitorSocket = new ServerSocket(monitorPort);
         monitorListener = new MonitorListener(this);
         monitorListener.start();
         workingSocket = new ServerSocket(workingPort);
         workerListener = new WorkerListener(this);
         workerListener.start();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

   public void close() {
      try {
         workingSocket.close();
         monitorSocket.close();
      } catch (Exception e) {
         e.printStackTrace();
         // TODO: handle exception
      }
   }

   public void acceptClients(boolean ok) {
      try {
         if (ok) {
            if (workingSocket == null || workingSocket.isClosed()) {
               workingSocket = new ServerSocket(workingPort);
            }
         } else {
            workingSocket.close();
         }
         AppProps.ACCEPT_CLIENTS = ok;
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   public ServerSocket getMonitorSocket() {
      return monitorSocket;
   }

   public void setMonitorSocket(ServerSocket monitorSocket) {
      this.monitorSocket = monitorSocket;
   }

   public ServerSocket getWorkingSocket() {
      return workingSocket;
   }

   public void setWorkingSocket(ServerSocket workingSocket) {
      this.workingSocket = workingSocket;
   }

   public HashSet<Worker> getWorkerSet() {
      return workerSet;
   }

   public void setWorkerSet(HashSet<Worker> workerSet) {
      this.workerSet = workerSet;
   }

   public void list() {
      int x = 0;
      for (Worker w : workerSet) {
         log.debug(String.format("%d. %s", x++, w.toString()));
      }
   }

   public void setupJob(String alphabet, int len, int hash) {
      ServerJob job = new ServerJob(this);
      Alphabet a = new Alphabet();
      a.add(alphabet);
      job.setAlphabet(a);
      job.setLen(len);
      job.setHash(hash);
      currentJob = job;
      status = ServerStatus.INSTALLED;
   }

   public void startJob() {
      currentJob.start();
      status = ServerStatus.RUNNING;
   }

   public void stopJob() {
      currentJob.stopWork();
   }

   public void startSthOn(String name) {
      Worker ww = null;
      for (Worker w : workerSet) {
         if (w.getTitle().equals(name)) {
            ww = w;
            break;
         }
      }
      if (ww != null) {
         Message m = new Message();
         m.setType(MessageType.START);
         Alphabet a = new Alphabet();
         a.add("a-d");
         String alf = a.toString();
         int len = 10;
         long start = 1;
         long end = Permutations.getPnm(5, alf.length());
         int hash = 979;
         m.addArg("alphabet", alf);
         m.addArg("len", "" + len);
         m.addArg("start", "" + start);
         m.addArg("end", "" + end);
         m.addArg("hash", "" + hash);
         ww.setAlphabet(a);
         ww.setLen(10);
         ww.setStart(start);
         ww.setEnd(end);
         ww.setHash(hash);
         ww.speak(m);
      }
   }

   public void stopSthOn(String name) {
      Worker ww = null;
      for (Worker w : workerSet) {
         if (w.getTitle().equals(name)) {
            ww = w;
            break;
         }
      }
      if (ww != null) {
         ww.speak(MessageType.STOP);
      }
   }
}
